package com.edu.hre.common.utils;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.navigator.menu.MenuComponent;
import net.sf.navigator.menu.MenuRepository;
import net.sf.navigator.util.LoadableResourceException;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.tiles.TilesRequestProcessor;
import org.jivesoftware.smackx.workgroup.packet.UserID;
import com.google.gwt.http.client.Response;
import com.google.gwt.i18n.client.Constants;
import com.lowagie.tools.concat_pdf;

import com.edu.hre.common.cache.PassiveDynaCache;
import com.edu.hre.common.encrypt.Encrypter;
import com.edu.hre.db.pojo.HreUser;
import com.edu.hre.db.pojo.HreUserRoleScreen;
import com.edu.hre.db.service.BaseService;
import com.edu.hre.db.utils.Compare;
import com.edu.hre.struts.action.admin.RoleGroupAction;

// Class xử lý chung cho mọi request tới action. kiểm tra quyền, phân quuyền để trả ra các menu tương ứng ... 
public class CustomRequestProcessor extends TilesRequestProcessor {
	
	public static MenuComponent[] menuComponent = null;
	private static final Logger logger = Logger.getLogger(CustomRequestProcessor.class);
	private static final BaseService baseService  = BeanFinder.getBean(BaseService.BEAN_NAME, BaseService.class);
	private static final PassiveDynaCache passiveDynaCache = BeanFinder.getBean(PassiveDynaCache.BEAN_NAME, PassiveDynaCache.class); 
	
	@Override
	protected boolean processRoles(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws IOException, ServletException {
		response.setContentType("text/html; charset=UTF-8");
		request.setCharacterEncoding("utf-8");
		if (menuComponent == null) {
			MenuRepository repositoryMenu = new MenuRepository();
			repositoryMenu.setLoadParam("/WEB-INF/menu-config-en.xml");
			repositoryMenu.setServletContext(getServletContext()); 
			try {
				repositoryMenu.load();
				menuComponent = repositoryMenu.getTopMenusAsArray();
			} catch (LoadableResourceException e) {  
				CommonUtils.println(e.getMessage());
			}
		} 
		CommonUtils.println(CommonUtils.getSourceCodeLocation());
		CommonUtils.println(request.getRequestURI() + "?" + ("null".equals(request.getQueryString() + "") ? "" : request.getQueryString()));
		HreUser user = (HreUser) request.getSession().getAttribute(RequestUtils.Attribute.USER_INFO);
		
		//========================= TEST ====================
//			if (user == null){
//				user = baseService.getFirstPojoAnd(new String[] { "userName", "userPassword" },
//						new int[] {Compare.EQUAL, Compare.EQUAL }, new String[] { "root", Encrypter.encodeMD5("123456") }, null, null, 0, HreUser.class);
//				request.getSession().setAttribute(RequestUtils.Attribute.USER_INFO, user);
//			}
		//========================= TEST ====================
			
		if (user == null && !mapping.getPath().contains("login")) {
			String linkTmp = request.getRequestURI();
			if(StringUtils.isNotBlank(request.getQueryString())){
				linkTmp += "?" + request.getQueryString();
			}
			CommonUtils.println("Url before login: " + linkTmp);
			request.getSession().setAttribute(RequestUtils.Attribute.URL_BEFORE_LOGIN, linkTmp);
			response.sendRedirect(request.getContextPath() + "/login.jsp");
			return false;
		} else if(user == null){
			return true;
		}
		if(!hasAuthen(request, mapping)){
			response.sendError(Response.SC_BAD_REQUEST);
			return false;
		}  
		
		String key = RequestUtils.Attribute.MENU_ROLES + user.getUserRoleId();
		String htmlMenu = (String) passiveDynaCache.getCachedItem(key);
		if(StringUtils.isBlank(htmlMenu)){
			List<HreUserRoleScreen> listUserRoleScreen = baseService.getPojos("userRoleId", Compare.EQUAL, new Integer(user.getUserRoleId()), null, null, 0, 0, HreUserRoleScreen.class);
			StringBuilder htmlMenuTag = new StringBuilder();
			tagMenusByRoles(request, listUserRoleScreen, menuComponent, htmlMenuTag, 1, user.getUserRoleId()); 
			htmlMenu = htmlMenuTag.toString();
		}
		passiveDynaCache.setCachedItem(key, PassiveDynaCache.TIMEOUT_3_HOURS, htmlMenu);
		return true;
	}
	 

	private boolean hasAuthen(HttpServletRequest request, ActionMapping mapping) { 
		CommonUtils.println("mapping.getRoles() = " + mapping.getRoles());
		if("login".equalsIgnoreCase(mapping.getName())){
			return true;
		}
		if(request.getAttribute(RequestUtils.Attribute.AUTHENTICATED) != null){
			return true;
		}
		HreUser user = (HreUser) request.getSession().getAttribute(RequestUtils.Attribute.USER_INFO);
		if(user == null){
			return false;
		}
		if("#".equalsIgnoreCase(mapping.getRoles())){
			HreUserRoleScreen userRoleScreen = new HreUserRoleScreen(user.getUserRoleId(), true, true, true, true, mapping.getRoles());
			request.getSession().setAttribute(RequestUtils.Attribute.HreUserRoleScreen, userRoleScreen);
			return true;
		}
		HreUserRoleScreen userRoleScreen = baseService.getFirstPojoAnd(new String[]{"userRoleId", "actionName"},
				new int[]{Compare.EQUAL, Compare.EQUAL}, new Object[]{user.getUserRoleId(), mapping.getRoles()} 
				, null, null, 0, HreUserRoleScreen.class);
		
		// =============================================================
//		System.out.println(mapping.getPath());
//		if("/empPersonalDetailUpdate".equalsIgnoreCase(mapping.getPath())
//				|| "/employeePersonal".equalsIgnoreCase(mapping.getPath())){
//			return true; 
//		}
		// =============================================================
		
		if(userRoleScreen != null){
			if(user.getUserRoleId() == 1){ // admin
				userRoleScreen.setCanCreate(true);
				userRoleScreen.setCanRead(true);
				userRoleScreen.setCanDelete(true);
				userRoleScreen.setCanUpdate(true);
				baseService.saveOrUpdate(userRoleScreen);
			}
			request.getSession().setAttribute(RequestUtils.Attribute.HreUserRoleScreen, userRoleScreen);
		} else if(user.getUserRoleId() == 1){ // admin
			HreUserRoleScreen tmp = new HreUserRoleScreen(user.getUserRoleId(), true, true, true, true, mapping.getRoles());
			request.getSession().setAttribute(RequestUtils.Attribute.HreUserRoleScreen, tmp);
			baseService.saveOrUpdate(tmp);
			return true;
		} else {
			return false;
		}
		if(!userRoleScreen.isCanRead()){
			return false;
		}
		if(!userRoleScreen.isCanCreate() && !userRoleScreen.isCanDelete() && !userRoleScreen.isCanRead() && !userRoleScreen.isCanUpdate()){
			return false;
		}  
		if(!userRoleScreen.isCanCreate() && request.getParameter("btnAdd") != null){
			return false;
		}
		if(!userRoleScreen.isCanCreate() && request.getParameter("btnInsert") != null){
			return false;
		}
		if(!userRoleScreen.isCanDelete() && request.getParameter(StringConstants.BTN_DELETE) != null){
			return false;
		}
		if(!userRoleScreen.isCanUpdate() && request.getParameter("btnUpdate") != null){
			return false;
		}
		if(!userRoleScreen.isCanUpdate() && request.getParameter("btnSave") != null){
			return false;
		}
		if(!userRoleScreen.isCanUpdate() && request.getParameter("btnEdit") != null){
			return false;
		}
		if(!userRoleScreen.isCanRead() && request.getParameter("btnRead") != null){
			return false;
		}
		if(!userRoleScreen.isCanRead() && request.getParameter("btnView") != null){
			return false;
		}
		return true;
	}


	private  void tagMenusByRoles(HttpServletRequest request, List<HreUserRoleScreen> listUserRoleScreen,
			MenuComponent[] menuComponent, StringBuilder htmlMenuTag, int level, int userRoleID) {
		for (int i = 0; menuComponent != null && i < menuComponent.length; i++) { 
			MenuComponent[] childs = menuComponent[i].getMenuComponents();
			if("hidden_menu".equalsIgnoreCase(menuComponent[i].getAlign())){
				continue;
			}
			String actionPath = "#";
			if(StringUtils.isNotBlank(menuComponent[i].getPage()) && !"#".equals(menuComponent[i].getPage())){
				actionPath = request.getContextPath() + menuComponent[i].getPage();
			}
			String idATag = "";
			if(StringUtils.isNotBlank(menuComponent[i].getTarget())){
				idATag = "id=\"" + menuComponent[i].getTarget() + "\"";
			}
			String space = getSpace(level);
			if(level == 1){
				htmlMenuTag.append(space + "<li class=\"l1\" id=\"" + menuComponent[i].getTitle().toLowerCase() + "\" onmouseover=\"topMenuHover();\">");
				htmlMenuTag.append(space + "	<a " + idATag + " href=\"" + (actionPath) + "\" class=\"l1_link\">");
				htmlMenuTag.append(space + "		<span class=\"drop\">" + menuComponent[i].getTitle() + "</span>");
				htmlMenuTag.append(space + "	</a>");
			} else {
				String styleGray = "";
				String actionName =  RoleGroupAction.normalizeActionName(menuComponent[i].getPage());
				if(userRoleID != 1 && !"#".equals(actionName) && !"enable".equalsIgnoreCase(menuComponent[i].getOnclick())){
					HreUserRoleScreen role = getRoleScreen(listUserRoleScreen, actionName);
					if(role == null || !role.isCanRead()){
						styleGray = " style=\"color: gray;\" ";
						actionPath = "#";
					}
				}
				htmlMenuTag.append(space + "<li class=\"l" + level + "\">");
				if(childs != null && childs.length != 0){
					htmlMenuTag.append(space + "	<a " + idATag + " href=\"" + (actionPath) + "\" class=\"l" + level + "_link parent l" + (level + 1) + "_link\">");
				} else {
					htmlMenuTag.append(space + "	<a " + idATag + " href=\"" + (actionPath) + "\" class=\"l" + level + "_link\">");
				}
				htmlMenuTag.append(space + "		<span" + styleGray + ">" + menuComponent[i].getTitle() + "</span>");
				htmlMenuTag.append(space + "	</a>");
			}
			if(childs != null && childs.length != 0){ 
				htmlMenuTag.append(space + "	<ul class=\"l" + (level + 1) + "\" style=\"left: -999em;\">");
				tagMenusByRoles(request, listUserRoleScreen, childs, htmlMenuTag, level + 1, userRoleID);
				htmlMenuTag.append(space + "	</ul>");
			} 
			htmlMenuTag.append(space + "</li>" ); 
		}   
	}
	
	private HreUserRoleScreen getRoleScreen(List<HreUserRoleScreen> listUserRoleScreen, String actionName){
		for(int i = 0; listUserRoleScreen != null && i < listUserRoleScreen.size(); i ++){
			HreUserRoleScreen screen = listUserRoleScreen.get(i);
			if(actionName.equals(screen.getActionName())){
				return screen;
			}
		}
		return null;
	}
	
	private String getSpace(int level){
		String s = "\n";
		for(int i = 0; i < level; i++){
			s += "	";
		}
		return s;
	}
	 
}
